﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236

namespace ShieldTunnel
{
	public sealed partial class GeneralRiskEvalPanel : UserControl
	{
		public GeneralRiskEvalPanel()
		{
			this.InitializeComponent();
		}

		private void ButtonEvalGeneralRisk_OnClick(object sender, RoutedEventArgs e)
		{
			var gasContentRadioButtons = new[]
			{
				(RadioGasContent1, 3),
				(RadioGasContent2, 2),
				(RadioGasContent3, 1),
				(RadioGasContent4, 0),
			};
			var waterContentRadioButtons = new[]
			{
				(RadioWaterContent1, 3),
				(RadioWaterContent2, 2),
				(RadioWaterContent3, 1),
				(RadioWaterContent4, 0),
			};

			var tunnelLength = double.Parse(TextBoxTunnelLength.Value.ToString());
			var weakRockLength = double.Parse(TextBoxWeakRockLength.Value.ToString());
			var tunnelDiameter = double.Parse(TextBoxTunnelDiameter.Value.ToString());
			var tunnelDepth = double.Parse(TextBoxTunnelDepth.Value.ToString());

			var gasContent = gasContentRadioButtons.First(rb => rb.Item1.IsChecked == true).Item2;
			var waterContent = waterContentRadioButtons.First(rb => rb.Item1.IsChecked == true).Item2;
			var adjacent = double.Parse(TextBoxAdjacent.Value.ToString());

			Debug.Assert(weakRockLength <= tunnelLength);
			var a = MatchLevel(weakRockLength / tunnelLength,
				new[] { 0d, 0.2d, 0.4d, 0.7d, 0.95d, 1.0d },
				new[] { 0, 1, 2, 3, 4 });
			var b = gasContent;
			var c = waterContent;
			var G = a + b + c;
			var D = MatchLevel(tunnelDiameter,
				new[] { 0d, 3.5d, 6d, 14d, 17d, double.MaxValue },
				new[] { 0, 1, 2, 3, 4 });
			var L = MatchLevel(tunnelLength,
				new[] { 0d, 500d, 1000d, 3000d, double.MaxValue },
				new[] { 1, 2, 3, 4 });
			var B = MatchLevel(tunnelDepth,
				new[] { 0d, 6d, 12d, 18d, double.MaxValue },
				new[] { 4, 3, 2, 1 });
			var N = MatchLevel(adjacent / tunnelDiameter,
				new[] { 0d, 0.3d, 0.7d, 1.0d, double.MaxValue },
				new[] { 4, 3, 2, 1 });
			var R = G * (D + L + B + N);

			var evalScoreItems = new List<EvalScoreItem>()
			{
				new EvalScoreItem(1, -1, "地质G=a+b+c", G),
				new EvalScoreItem(2, 1, "围岩情况a", a),
				new EvalScoreItem(3, 1, "瓦斯含量b", b),
				new EvalScoreItem(4, 1, "富水情况c", c),
				new EvalScoreItem(5, -1, "盾构直径D", D),
				new EvalScoreItem(6, -1, "隧道全长L", L),
				new EvalScoreItem(7, -1, "隧道埋深B", L),
				new EvalScoreItem(8, -1, "与周围环境设施临近关系N", L),
				new EvalScoreItem(9, -1, "总分R=G(D+L+B+N)", R),
			};

			Debug.Assert(TreeGridGeneralRiskResult != null);
			TreeGridGeneralRiskResult.ItemsSource = null;
			TreeGridGeneralRiskResult.ItemsSource = evalScoreItems;
			TreeGridGeneralRiskResult.ExpandAllNodes();

			//
			// Eval general risk level
			//
			var riskLevel = MatchLevel(R,
				new[] { 0, 10, 17, 25, int.MaxValue },
				new[] { 1, 2, 3, 4 });

			var riskLevelString = new[]
			{
				"Ⅰ级（低度风险）",
				"Ⅱ级（中度风险）",
				"Ⅲ级（高度风险）",
				"Ⅳ级（极高风险）"
			}[riskLevel - 1];
			TextBlockRiskLevel.Text = riskLevelString;
			var riskLevelColor = new[]
			{
				Colors.Green,
				Colors.Blue,
				Colors.OrangeRed,
				Colors.DarkRed,
			}[riskLevel - 1];
			RectRiskLevelFill.Fill = new SolidColorBrush(riskLevelColor);
			RectRiskLevelFill.Width = RectRiskLevelFrame.ActualWidth * riskLevel / 4.0;

			var needSpecialRiskEval = riskLevel >= 3;
			TextBlockNeedSpecialRiskEval.Text = (needSpecialRiskEval ? "需要专项评估" : "不需要专项评估");
			TextBlockNeedSpecialRiskEval.Foreground = new SolidColorBrush(needSpecialRiskEval ? Colors.Red : Colors.Black);
		}

		private static TGrade MatchLevel<TScore, TGrade>(TScore score,
			IList<TScore> scores, IList<TGrade> grades)
			where TScore : IComparable
		{
			Debug.Assert(scores != null && grades != null && grades.Count >= 1
			             && scores.Count == grades.Count + 1);
			Debug.Assert(score.CompareTo(scores.First()) >= 0 && score.CompareTo(scores.Last()) <= 0);

			var grade = grades.Last();
			for (var i = 0; i < grades.Count; i++)
			{
				var lower = scores[i];
				var upper = scores[i + 1];
				Debug.Assert(lower.CompareTo(upper) < 0);
				if (score.CompareTo(lower) >= 0 && score.CompareTo(upper) < 0)
				{
					grade = grades[i];
					break;
				}
			}
			return grade;
		}

		#region Helper Classes

		public class EvalScoreItem
		{
			public EvalScoreItem(int id, int parentId, string scoreName, int score)
			{
				ID = id;
				ParentID = parentId;
				ScoreName = scoreName;
				Score = score;
			}

			public int ID { get; set; }
			public int ParentID { get; set; }
			public string ScoreName { get; set; }
			public int Score { get; set; }
		}

		#endregion
	}
}
